﻿//****************************************************************************
// Copyright (c) Microsoft Corporation. All rights reserved.
//****************************************************************************
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using Microsoft.FxCop.Sdk;

namespace Microsoft.FxCop.Rules.ASP.Security
{
    //
    //The ViewStateEncryptionMode property cannot be set in code.
    //It can only be set in the @ Page directive or in the <pages> element of the configuration file.
    //Values set in the @ Page directive override any values set in the configuration file.
    //ref : http://msdn.microsoft.com/en-us/library/system.web.ui.page.viewstateencryptionmode.aspx
    //
    // Only need to check in the BuildTree method
    class ViewStateEncryptionModeShouldBeAlways : BasePageIntrospectionRule
    {

        #region *** Constructor ***
        public ViewStateEncryptionModeShouldBeAlways()
            : base("ViewStateEncryptionModeShouldBeAlways")
        {
        }
        #endregion

        #region *** Methods ***

        #region *** BasePageRule ***
        protected override void CheckBuildControlTree(Method buildTreeMethod)
        {
            Instruction currentInstruction;
            Instruction peekInstruction;

            for (int i = 0; i < buildTreeMethod.Instructions.Count; i++)
            {
                currentInstruction = buildTreeMethod.Instructions[i];

                if (currentInstruction.OpCode == OpCode.Callvirt)
                {
                    if ((currentInstruction.Value as Method).Name.Name == "set_ViewStateEncryptionMode")
                    {
                        peekInstruction = buildTreeMethod.Instructions[i - 1];
                        switch (peekInstruction.OpCode)
                        {
                            // ViewStateEncryptionMode.Never;
                            case OpCode.Ldc_I4_2:       
                            // ViewStateEncryptionMode.Auto
                            case OpCode.Ldc_I4_0:       
                                ReportProblem();
                                return;
                            // ViewStateEncryptionMode.Always
                            case OpCode.Ldc_I4_1:
                                return;
                            default:
                                break;
                        }

                        return;
                    }
                }
            }

            // if we reach this point, it means the page left the ViewStateEncryptionMode to its default value of ViewStateEncrytionMode.Auto
            ReportProblem();
        }
        #endregion

        #endregion
    }
}
